<template>
  <div class="hotel-week-pre">
    <div class="top-section">
      <div class="header-wrapper">
        <h3 class="title">酒店周盈利预测表</h3>
      </div>
      <div class="form-wrapper">
        <div class="form-content">
          <div class="form-item">
            <span class="label">项目</span>
            <a-select v-model:value="currentCode" :options="hotelList" show-search :filter-option="filterOption" style="width: 200px" />
          </div>
          <div class="form-item">
            <span class="label">预测月份</span>
            <a-date-picker v-model:value="currentMonth" picker="month" style="width: 200px" :placeholder="'选择月份'" />
          </div>
          <div class="form-item">
            <span class="label">周</span>
            <a-select v-model:value="currentWeek" :options="weekList" style="width: 200px" />
          </div>
          <div class="form-item form-item-center">
            <span class="label">展示详细列</span>
            <a-switch v-model:checked="isDetail" />
          </div>
          <div class="form-item">
            <a-button type="primary" size="small" @click="handleSearch">查询</a-button>
            <a-button size="small" style="margin-left: 8px" @click="handleReset">重置</a-button>
            <div class="filter-icon-container">
              <img class="icon-screen" src="/@/assets/images/screening.png" @click="handleShowFilter" alt="筛选图标" :title="'过滤设置'" />
            </div>
          </div>
        </div>
      </div>
    </div>
    <div class="main-content">
      <TableCard
        class="card-flex-all"
        title="月度预测"
        :dataList="dataList"
        :columns="getDataColumns()"
        :scroll="tableHigh"
        :exportData="dataList"
        :loading="loading"
        :isPagination="false"
        :exportHeader="getExportHeader()"
        :exprotMerges="getExprotMerges()"
      />
    </div>
    <SearchFilterModal v-model:visible="showFilter" :fields="searchFormOptions" :visible="showFilter" @save="handleSaveFilter" />
  </div>
</template>

<script>
  import dayjs from 'dayjs';
  import * as MathUtil from '/@/utils/MathUtil';
  import * as DateUtil from '/@/utils/dateUtil';
  import TableCard from '/@/views/applications/ui/TableCard.vue';
  import { DatePicker, Switch, Button, Select } from 'ant-design-vue';
  import { defHttp } from '/@/utils/http/axios';
  import SearchFilterModal from '/@/views/applications/ui/SearchFilterModal.vue';

  export default {
    name: 'HotelWeekPre',
    components: {
      TableCard,
      ADatePicker: DatePicker,
      ASwitch: Switch,
      AButton: Button,
      ASelect: Select,
      SearchFilterModal,
    },

    data() {
      return {
        subjectList: [],
        showFilter: false,
        searchFormOptions: [
          {
            value: 'hotel',
            label: '项目',
            selected: true,
            showDetails: true,
          },
          {
            value: 'month',
            label: '预测月份',
            selected: true,
            showDetails: true,
          },
          {
            value: 'week',
            label: '周',
            selected: true,
            showDetails: true,
          },
          {
            value: 'detail',
            label: '展示详细列',
            selected: true,
            showDetails: true,
          },
        ],
        selectedFields: [],
        loading: false,
        tableHigh: { x: '100%', y: 'calc(60vh)' },
        isDetail: false,
        yearList: DateUtil.generateYearList().map((y) => ({
          label: `${y}年`,
          value: y,
        })),
        monthList: DateUtil.generateMonthList(),
        weekList: DateUtil.generateWeekList().map((w) => ({
          label: `第${w}周`,
          value: w,
        })),
        currentWeek: 1,
        currentMonth: dayjs(),
        hotelList: [],
        currentCode: '',
        dataList: [],
        dataColumns: [
          {
            title: '科目',
            dataIndex: 'subjectName',
            key: 'subjectName',
            width: 220,
            align: 'left',
            ellipsis: true,
            fixed: 'left',
          },
        ],
      };
    },

    created() {
      defHttp.get({ url: '/data/hotel/list' }, { isTransformResponse: false }).then((res) => {
        if (res.code === 200 && res.result.length > 0) {
          const resData = res.result;
          this.hotelList = resData
            .map((s) => ({
              label: s.name,
              value: s.code,
            }))
            .concat([
              {
                label: '酒店合计',
                value: resData.map((d) => d.code).join(','),
              },
            ]);
          this.currentCode = resData[0].code;
          this.fetchBaseInfo();
        }
      });
    },

    methods: {
      handleShowFilter() {
        this.showFilter = true;
      },

      handleSaveFilter(updatedFields) {
        this.selectedFields = updatedFields;
        this.searchFormOptions = updatedFields;

        // 更新表单显示
        const formWrapper = document.querySelector('.form-wrapper');
        if (formWrapper) {
          const hotelItem = formWrapper.querySelector('.form-item:nth-child(1)');
          const monthItem = formWrapper.querySelector('.form-item:nth-child(2)');
          const weekItem = formWrapper.querySelector('.form-item:nth-child(3)');
          const detailItem = formWrapper.querySelector('.form-item:nth-child(4)');

          if (hotelItem) {
            hotelItem.style.display = updatedFields.find((f) => f.value === 'hotel')?.selected ? 'flex' : 'none';
          }
          if (monthItem) {
            monthItem.style.display = updatedFields.find((f) => f.value === 'month')?.selected ? 'flex' : 'none';
          }
          if (weekItem) {
            weekItem.style.display = updatedFields.find((f) => f.value === 'week')?.selected ? 'flex' : 'none';
          }
          if (detailItem) {
            detailItem.style.display = updatedFields.find((f) => f.value === 'detail')?.selected ? 'flex' : 'none';
          }
        }

        // 重新查询数据
        this.fetchBaseInfo();
      },

      filterOption(input, option) {
        return option.label.toLowerCase().indexOf(input.toLowerCase()) >= 0;
      },

      fetchBaseInfo() {
        this.loading = true;
        const hotelMap = new Map(this.hotelList.map((item) => [item.value, item.label]));
        this.dataColumns[0].title = hotelMap.get(this.currentCode);

        Promise.all([
          defHttp.post({
            url: '/data/query',
            data: {
              labelCode: 'getHotelPresubject',
              sqlParams: [],
              pageIndex: 1,
              pageSize: 100,
            },
          }),
          defHttp.post({
            url: '/data/query',
            data: {
              labelCode: 'getHotelPreActualBudget',
              sqlParams: [
                {
                  key: 'code',
                  value: this.currentCode,
                },
                {
                  key: 'month',
                  value: this.currentMonth.format('YYYYMM'),
                },
                {
                  key: 'week',
                  value: this.currentWeek,
                },
              ],
              pageIndex: 1,
              pageSize: 5000,
            },
          }),
        ])
          .then(([res1, res2]) => {
            if (res1.datas.success && res1.datas.totalCount > 0) {
              this.subjectList = res1.datas.data;
            }
            if (res2.datas.success && res2.datas.totalCount > 0) {
              const incomeList = res2.datas.data;
              const valueKeys = {
                preFvalue: 'p',
                budgetFvalue: 'b',
                actualFvalue: 'a',
              };
              let colKeys = [];
              let dataList = this.subjectList.map((s) => {
                let d = {
                  subjectCode: s.code,
                  subjectName: s.name,
                  showFormatter: s.showFormatter || '',
                };
                if (s.calMode === 'DEFAULT') {
                  Object.keys(valueKeys).forEach((n) => {
                    let sum = 0;
                    let acc = 0;
                    let qd = {};
                    this.monthList
                      .filter(m => m && m.name)
                      .map((m) => m.value)
                      .forEach((m) => {
                        const i = incomeList.filter((i) => i.subjectCode === s.code && i.calMonth.slice(-2) === m);
                        const fvalue = i.length > 0 ? Math.round(i[0][n]) : 0;
                        d[`${valueKeys[n]}${m}`] = fvalue;
                        sum += fvalue;
                        if (m <= this.currentMonth.format('MM')) {
                          acc += fvalue;
                        }
                        const qdKey = `${valueKeys[n]}q${DateUtil.getQuarter(m)}`;
                        qd[qdKey] = (qd[qdKey] || 0) + fvalue;
                      });
                    d[`${valueKeys[n]}year`] = sum;
                    d[`${valueKeys[n]}acc`] = acc;
                    d = { ...d, ...qd };
                  });
                  this.wrapData(d);
                  if (colKeys.length === 0) {
                    colKeys = Object.keys(d).filter((k) => !['subjectCode', 'subjectName', 'showFormatter'].includes(k) && !/^[dc]/.test(k));
                  }
                }
                return d;
              });
              this.subjectList.forEach((s) => {
                if (s.calMode === 'AUTO') {
                  dataList.forEach((d) => {
                    if (d.subjectCode === s.code && colKeys.length > 0) {
                      colKeys.forEach((c) => {
                        const replacedFormula = s.formula.replace(/#\{(\d+)\}/g, (_, code) => dataList.filter((l) => l.subjectCode === code)[0][c]);
                        d[c] = eval(replacedFormula) || 0;
                      });
                      this.wrapData(d);
                    }
                  });
                }
              });
              this.dataList = dataList;
            } else {
              this.dataList = [];
            }
            this.loading = false;
          })
          .catch((error) => {
            console.error('获取数据失败：', error);
            this.loading = false;
            this.dataList = [];
          });
      },

      handleSearch() {
        this.fetchBaseInfo();
      },

      handleReset() {
        this.currentMonth = dayjs();
        this.currentWeek = 1;
        this.isDetail = false;
        this.fetchBaseInfo();
      },

      getDataColumns() {
        let dataColumns = this.dataColumns;
        const colKeys = [
          { prefix: 'p', title: '月度预测' },
          { prefix: 'b', title: '预算' },
          { prefix: 'a', title: '去年同期' },
          { prefix: 'c', title: '预测VS预算' },
          { prefix: 'd', title: '预测VS去年同期' },
        ];

        colKeys.forEach((c, ci) => {
          if (this.isDetail) {
            dataColumns = dataColumns.concat(
              DateUtil.generateMonthList()
                .filter(m => m && m.name)
                .map((m, index) => ({
                  title: m.name,
                  dataIndex: `${c.prefix}${m.value}`,
                  key: `${c.prefix}${m.value}`,
                  width: index === 5 ? 140 : 120,
                  align: 'right',
                  className: ci % 2 === 0 ? '' : 'table-header-color',
                  customRender: (val) => this.colRender(val.text, val.record),
                }))
            );
          }
          dataColumns = dataColumns.concat([
            {
              title: this.isDetail ? '' : c.title,
              dataIndex: `${c.prefix}year`,
              width: 140,
              align: 'right',
              className: ci % 2 === 0 ? '' : 'table-header-color',
              children: [
                {
                  title: '全年',
                  dataIndex: `${c.prefix}year`,
                  key: `${c.prefix}year`,
                  width: 140,
                  align: 'right',
                  className: ci % 2 === 0 ? '' : 'table-header-color',
                  customRender: (val) => this.colRender(val.text, val.record),
                },
              ],
            },
            {
              dataIndex: `${c.prefix}acc`,
              width: 120,
              align: 'right',
              className: ci % 2 === 0 ? '' : 'table-header-color',
              children: [
                {
                  title: '年累计',
                  dataIndex: `${c.prefix}acc`,
                  key: `${c.prefix}acc`,
                  width: 120,
                  align: 'right',
                  className: ci % 2 === 0 ? '' : 'table-header-color',
                  customRender: (val) => this.colRender(val.text, val.record),
                },
              ],
            },
          ]);
          if (this.isDetail) {
            dataColumns = dataColumns.concat(
              DateUtil.generateQuarterList()
                .filter(m => m && m.name)
                .map((m) => ({
                  dataIndex: `${c.prefix}q${m.value}`,
                  width: 120,
                  align: 'right',
                  className: ci % 2 === 0 ? '' : 'table-header-color',
                  children: [
                    {
                      title: m.name,
                      dataIndex: `${c.prefix}q${m.value}`,
                      key: `${c.prefix}q${m.value}`,
                      width: 120,
                      align: 'right',
                      className: ci % 2 === 0 ? '' : 'table-header-color',
                      customRender: (val) => this.colRender(val.text, val.record),
                    },
                  ],
                }))
            );
          }
        });
        return dataColumns;
      },

      getExportHeader() {
        let exportHeader = [this.getDataColumns().map((c) => c.title), this.getDataColumns().map((c) => (c.children ? c.children[0].title : null))];
        if (this.isDetail) {
          exportHeader[0][1] = exportHeader[0][6];
          exportHeader[0][19] = exportHeader[0][24];
          exportHeader[0][37] = exportHeader[0][42];
          exportHeader[0][55] = exportHeader[0][60];
          exportHeader[0][73] = exportHeader[0][78];
        }
        return exportHeader;
      },

      getExprotMerges() {
        return [
          { s: { r: 0, c: 0 }, e: { r: 1, c: 0 } },
          { s: { r: 0, c: 1 }, e: { r: 0, c: this.isDetail ? 18 : 2 } },
          {
            s: { r: 0, c: this.isDetail ? 19 : 3 },
            e: { r: 0, c: this.isDetail ? 36 : 4 },
          },
          {
            s: { r: 0, c: this.isDetail ? 37 : 5 },
            e: { r: 0, c: this.isDetail ? 54 : 6 },
          },
          {
            s: { r: 0, c: this.isDetail ? 55 : 7 },
            e: { r: 0, c: this.isDetail ? 72 : 8 },
          },
          {
            s: { r: 0, c: this.isDetail ? 73 : 9 },
            e: { r: 0, c: this.isDetail ? 90 : 10 },
          },
        ];
      },

      wrapData(d) {
        const cKeys = {
          c: 'p,b',
          d: 'p,a',
        };
        Object.keys(cKeys).forEach((c) => {
          const prefixs = cKeys[c].split(',');
          Object.keys(d)
            .filter((k) => k[0] === prefixs[0])
            .forEach((k) => {
              const suffix = k.slice(1);
              d[`${c}${suffix}`] = d[k] - d[`${prefixs[1]}${suffix}`];
            });
        });
      },

      colRender(val, record) {
        if (record && record.showFormatter) {
          const [methodName, ...params] = record.showFormatter.split('|');
          if (typeof this[methodName] === 'function') {
            return this[methodName](val, ...params);
          }
        }
        return val;
      },

      percentFormatter(value) {
        return (value * 100).toFixed(0) + '%';
      },

      percentTipFormatter(params) {
        return (
          params[0].axisValue +
          '<br />' +
          params
            .map((p) => {
              return `${p.marker} ${p.seriesName}: ${(p.data * 100).toFixed(0)}%`;
            })
            .join('<br />')
        );
      },

      currencyWFormatter(value, dot = 2, unit = '万') {
        return MathUtil.currencyWFormatter(value, dot, unit);
      },

      currencyWNFormatter(value, dot = 0) {
        return MathUtil.currencyWNFormatter(value, dot);
      },

      percent2DFormatter(value, dot = 2) {
        return MathUtil.percent2DFormatter(value, dot);
      },

      diffPercent2Formatter(thisData, lastData, dot = 2) {
        return MathUtil.diffPercent2Formatter(thisData, lastData, dot);
      },

      dot2Formatter(value, dot = 2) {
        return MathUtil.dot2Formatter(value, dot);
      },

      dateRangeFormatter(dataRange) {
        return DateUtil.dateRangeFormatter(dataRange);
      },

      dateFormatter(data) {
        return DateUtil.dateFormatter(data);
      },

      monthFormatter(data) {
        return DateUtil.monthFormatter(data);
      },

      safeDivide(numerator, denominator) {
        return MathUtil.safeDivide(numerator, denominator);
      },
    },
  };
</script>

<style lang="less" scoped>
  .hotel-week-pre {
    display: flex;
    flex-direction: column;
    background-color: #fff;

    .top-section {
      display: flex;
      align-items: center;
      justify-content: space-between;
      background: #fff;
      padding: 24px 24px 0;
      margin-bottom: 24px;

      .header-wrapper {
        margin-bottom: 0;
      }

      .form-wrapper {
        margin-bottom: 0;
      }

      .title {
        font-size: 18px;
        font-weight: 600;
        color: #1a253b;
        margin: 0;
        padding: 0;
      }
    }

    .form-wrapper {
      margin-bottom: 24px;

      .form-content {
        display: flex;
        align-items: center;
        flex-wrap: wrap;
        gap: 16px;
      }

      .form-item {
        display: flex;
        align-items: center;

        .label {
          margin-right: 12px;
          color: #1677ff;
          font-size: 14px;
          white-space: nowrap;
        }
      }

      .form-item-center {
        justify-content: center;
      }

      .filter-icon-container {
        display: inline-block;
        padding: 4px;
        border-radius: 4px;
        transition: all 0.3s ease;
        margin-left: 10px;
      }

      .icon-screen {
        width: 20px;
        height: 20px;
        cursor: pointer;
        transition: all 0.3s ease;
        object-fit: scale-down;
      }

      .filter-icon-container:hover {
        background-color: #e1ebf9;
      }

      .icon-screen:hover {
        transform: scale(1.1);
        opacity: 0.8;
      }
    }

    .main-content {
      flex: 1;
      background: @content-inside-bg;
      padding: 16px 0;
      overflow: hidden;

      .card-flex-all {
        height: 100%;
      }
    }
  }
</style>
